package com.axzhengxin.platform.common.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.axzhengxin.platform.afterloan.mapper.FspCorInfMapper;
import com.axzhengxin.platform.axcube.service.IAxCubeService;
import com.axzhengxin.platform.axcube.transf.desc.SjqJbxx;
import com.axzhengxin.platform.common.props.AuthFileSftpProps;
import com.axzhengxin.platform.common.service.IBizCommonService;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * BizCommonServiceImpl
 *
 * @author jiangnan
 * @date 2021/3/23
 */
@Slf4j
@Service
public class BizCommonServiceImpl implements IBizCommonService {

    /**
     * 黑名单读数据超时
     */
    private static final Integer BLACK_NAME_LIST_TIME_OUT = 30 * 1000;

    /**
     * 信用报告读数据超时
     */
    private static final Integer CREDIT_REPORT_TIME_OUT = 20 * 60 * 1000;

    @Value("${graph-url}")
    private String graphUrl;

    @Value("${black-name-list-url}")
    private String blackNameListUrl;

    @Value("${ax-score-url}")
    private String axScoreUrl;

    @Value("${pdf-load-url}")
    private String pdfLoadUrl;

    @Autowired
    private FspCorInfMapper fspCorInfMapper;

    @Autowired
    private AuthFileSftpProps sftpProps;

    @Autowired
    private IAxCubeService axCubeService;

    @Override
    public GraphRedirectResponse graphRedirect(String customerName) {
        return new GraphRedirectResponse()
                .setUsername("admin")
                .setChannel("shuijingqiu")
                .setName(customerName)
                .setUrl(graphUrl + "/CristalBallgraph.servlet");
    }

    @Override
    public BlackNameListResponse blackNameList(String customerId) {
        AtomicBoolean noIntgdata = new AtomicBoolean(true);
        return Optional.ofNullable(fspCorInfMapper.selectFspCorInfById(customerId))
                .filter(fspCorInf -> StrUtil.isNotBlank(fspCorInf.getAuthFilePath()))
                .map(fspCorInf -> {
                    SjqJbxx sjqJbxx = axCubeService.getEntInfo(fspCorInf.getName());
                    if (Objects.nonNull(sjqJbxx)) {
                        noIntgdata.set(false);
                        return new JSONObject()
                                .putOnce("authFile", StrUtil.trimToEmpty(fspCorInf.getAuthFilePath()))
                                .putOnce("authftp_host", sftpProps.getHost() + ":" + sftpProps.getPort())
                                .putOnce("authftp_name", sftpProps.getUsername())
                                .putOnce("authftp_pass", sftpProps.getPassword())
                                .putOnce("conApplyNum", 0)
                                .putOnce("frApplyNum", 0)
                                .putOnce("serviceid", "axblacklist")
                                .putOnce("cardId", StrUtil.trimToEmpty(fspCorInf.getLegalPersonCertId()))
                                .putOnce("elecCustomerId", StrUtil.trimToEmpty(fspCorInf.getPowerUserNumber()))
                                .putOnce("entName", StrUtil.trimToEmpty(fspCorInf.getName()))
                                .putOnce("lerep", StrUtil.trimToEmpty(sjqJbxx.getLerep()))
                                .putOnce("shxydm", StrUtil.trimToEmpty(sjqJbxx.getUniscid()))
                                .putOnce("orgConsumerSeqNo", IdUtils.simpleUUID());
                    } else {
                        return new JSONObject();
                    }
                })
                .filter(CollUtil::isNotEmpty)
                .map(request -> {
                    try {
                        log.info("请求黑名单服务报文:{}", request.toString());
                        return HttpUtil.createPost(blackNameListUrl)
                                .body(request.toString())
                                .contentType(MediaType.APPLICATION_JSON_VALUE)
                                .setReadTimeout(BLACK_NAME_LIST_TIME_OUT)
                                .execute();
                    } catch (Exception ex) {
                        log.error("请求黑名单服务时发生异常", ex);
                        return null;
                    }
                })
                .filter(HttpResponse::isOk)
                .map(HttpResponse::body)
                .filter(StrUtil::isNotBlank)
                .map(respData -> {
                    log.info("黑名单服务响应报文:{}", respData);
                    return respData;
                })
                .map(JSONUtil::parseObj)
                .filter(resp -> resp.containsKey("rescode"))
                .filter(resp -> "000000".equalsIgnoreCase(resp.getStr("rescode")))
                .map(resp -> resp.getStr("result"))
                .map(JSONUtil::parseObj)
                .map(result -> result.getStr("result"))
                .map(result -> Stream.of(result.split(","))
                        .map(ruleCode -> DictUtils.getDictLabel("black_name_rule", ruleCode))
                        .filter(StrUtil::isNotBlank)
                        .collect(Collectors.toList()))
                .map(BlackNameListResponse::init)
                .orElseGet(() -> {
                    if (noIntgdata.get()) {
                        return BlackNameListResponse.unauthorized();
                    }
                    return BlackNameListResponse.error();
                });
    }

    @Override
    public AxScoreRedirectResponse axScoreRedirect() {
        return new AxScoreRedirectResponse().setUrl(axScoreUrl);
    }

    @Override
    public CreditReportResponse creditReport(String customerId) {
        AtomicBoolean noAuth = new AtomicBoolean(true);
        return Optional.ofNullable(fspCorInfMapper.selectFspCorInfById(customerId))
                .filter(fspCorInf -> StrUtil.isNotBlank(fspCorInf.getAuthFilePath()))
                .map(fspCorInf -> {
                    noAuth.set(false);
                    return fspCorInf;
                })
                .map(fspCorInf -> new JSONObject()
                        .putOnce("entName", fspCorInf.getName())
                        .putOnce("userName", "admin")
                        .putOnce("userType", "1")
                        .putOnce("reportType", "general")
                        .putOnce("channel", "5")
                        .putOnce("authFile", fspCorInf.getAuthFilePath())
                        .putOnce("elecCustomerId", fspCorInf.getPowerUserNumber())
                        .putOnce("customName", SecurityUtils.getLoginUser().getUsername())
                        .putOnce("userId", SecurityUtils.getLoginUser().getUser().getUserId())
                        .putOnce("deptId", SecurityUtils.getLoginUser().getUser().getDeptId()))
                .map(request -> {
                    try {
                        log.info("信用报告服务请求报文:{}", request.toString());
                        return HttpUtil.createPost(pdfLoadUrl)
                                .body(request.toString())
                                .timeout(CREDIT_REPORT_TIME_OUT)
                                .contentType(MediaType.TEXT_PLAIN_VALUE)
                                .execute();
                    } catch (Exception ex) {
                        log.error("请求信用报告服务时发生异常", ex);
                        return null;
                    }
                })
                .filter(HttpResponse::isOk)
                .map(HttpResponse::body)
                .map(body -> {
                    log.info("信用报告服务响应报文:{}", body);
                    return body;
                })
                .filter(StrUtil::isNotBlank)
                .map(JSONUtil::parseObj)
                .filter(response -> response.containsKey("code"))
                .filter(response -> "200100".equals(response.getStr("code")))
                .map(response -> response.getJSONObject("data"))
                .map(data -> data.getStr("htmlStr"))
                .map(CreditReportResponse::init)
                .orElseGet(() -> {
                    if (noAuth.get()) {
                        return CreditReportResponse.unauthorized();
                    } else {
                        return CreditReportResponse.init(StrUtil.EMPTY);
                    }
                });
    }


}
